package cn.hicard.auth.web;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;

/**
 * 权限认证工具类，初版beat-0.1
 * @author zhangy
 *
 */
public class Authentication {
	
	private static Logger logger = Logger.getLogger("frameLogger");

	/**
	 * 验证权限：用户是否拥有路径url的访问权限
	 * 注意，如果该url未注册，则直接返回通过true
	 * @param userTree用户权限树
	 * @param path访问路径
	 * @return
	 */
	public static boolean authPath(Node allTree, Node userTree, String path){		
		// 为方便切割，对路径作下处理
		if(path.startsWith("/")){
			path = path.substring(1);
		}
		if(path.endsWith("/")){
			path = path.substring(0, path.length()-1);
		}
		// 切割后的路径就是树形结构下的某一分枝的ID组成的路径
		String[] sourceIds = path.split("/");	
		
		boolean pass = true;
		StringBuilder passLog = new StringBuilder("/"+sourceIds[0]);
		// 如果是集中式权限管理，则从根路径[项目名称]开始逐级验证，i从0开始
		// 这里是分散式，各项目各自管理权限，就不验证根路径了，i从1开始
		for (int i = 1; i < sourceIds.length; i++) {
			passLog.append("/"+sourceIds[i]);
			// 同时逐级取出节点
			allTree = allTree.findChild(sourceIds[i]);
			if(allTree != null){		
				
				if(userTree != null) userTree = userTree.findChild(sourceIds[i]);
				
				if(userTree == null){
					pass = false;
					logger.trace("用户无权限，不过:" + sourceIds[i]);
					break;
				}else{
					logger.trace("用户拥有权限，通过:" + passLog.toString());
				}
			}else{
				logger.trace("总资源未注册，通过:"  + passLog.toString());
				break;
			}
		}
		return pass;
	}

	
	/**
	 * 验证权限：过滤掉用户无权访问的HTML代码
	 * @param allTree总资源权限树
	 * @param useTree用户拥有的角色资源树
	 * @param html即将返回给浏览器的网页HTML文本
	 * @return
	 */
	public static String authHtml(Node allTree, Node userTree, String html){
		
		Document doc = Jsoup.parse(html, "", Parser.htmlParser());
		
		String bodyId = doc.body().id();
		
		// 页面未注册的 id 直接全部返回不验证
		if(bodyId.length() == 0){
			return html;
		}
		// 使用约定，html的boyd的id以字母b开头，加它在权限系统中注册的主键数字
		bodyId = bodyId.substring(1);
		
		// 到指定节点下查找用户相对于总资源没有权限的HTML节点ID
		List<String> htmlTagIds = findNotExist(allTree, userTree, Integer.valueOf(bodyId));
		// 移除用户无权访问的部分
		for (String htmlId : htmlTagIds) {
			Element tag = doc.getElementById(htmlId);
			if(tag != null) tag.remove();
		}		
		return doc.html();
	}
	
	/**
	 * 查找用户没有权限的资源ID，这个方法用于查找当前HTML页面上用户无法权访问的HTML元素的ID集合
	 * @return
	 */
	public static List<String> findNotExist(Node allTree, Node userTree, int startPk){
		List<String> list = new ArrayList<String>();
		// 找到总资源的[查找]起始PK节点
		Node allStart = null;
		if(allTree != null){
			allStart = allTree.findByPk(startPk);
		} 
		// 找到用户拥有的资源[查找]的起始PK节点
		Node userStart = null;
		if(userTree != null){
			userStart = userTree.findByPk(startPk);
		}
		// 将树转为List集合
		List<Node> allNodes = new ArrayList<Node>();
		if(allStart != null){
			allStart.listNode(allNodes);
		}		
		List<Node> userNodes = new ArrayList<Node>();
		if(userStart != null){
			userStart.listNode(userNodes);
		}		
		StringBuilder notpassLog = new StringBuilder();
		// 找到相对不存在的资源ID
		for (Node node : allNodes) {
			if( ! userNodes.contains(node)){
				list.add(node.getControlid());
				notpassLog.append(node.getControlid() + ",");
			}
		}
		if(notpassLog.length()>0){
			notpassLog.deleteCharAt(notpassLog.length()-1);
			logger.debug("用户无权限的Html页面资源id集合：" + notpassLog);
		}else{
			logger.debug("用户拥有整个Html页面资源的权限");
		}
		return list;
	}
				
}
